package mspbots.timedoctor.client.oauth;

import mspbots.timedoctor.client.core.BaseGenericService;
import org.springframework.expression.ExpressionException;
import reactor.core.publisher.Mono;

import java.util.Map;

/**
 * data.connector.doctor.oauth.AuthService
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2020/5/6
 */
public abstract class BaseAuthService extends BaseGenericService {

    protected final String REDIS_TOKEN_KEY_PREFIX = "oauth:";

    public Mono<String> getToken(Long tenantId) {

        Mono<String> accessTokenMono = this.reactiveRedisTemplate.opsForValue()
                .get(this.REDIS_KEY_PREFIX + this.REDIS_TOKEN_KEY_PREFIX + tenantId + ":token")
                .map(result -> this.objectMapper.convertValue(result, String.class));

        Mono<AuthorizationCode> authorizationCodeMono = this.reactiveRedisTemplate.opsForValue()
                .get(this.REDIS_KEY_PREFIX + this.REDIS_TOKEN_KEY_PREFIX + tenantId + ":authorization")
                .switchIfEmpty(Mono.defer(() -> Mono.error(new ExpressionException("Your access token is empty,Allow access your account."))))
                .map(result -> this.objectMapper.convertValue(result, AuthorizationCode.class));

        return accessTokenMono.switchIfEmpty(authorizationCodeMono
                .flatMap(authorizationCode -> this.refreshToken(tenantId, authorizationCode)))
                .onErrorResume(err -> Mono.just(err.getMessage()));

    }

    public abstract Mono<String> authToken(Map<String, Object> params);

    protected abstract Mono<String> refreshToken(Long tenantId, AuthorizationCode authorizationCode);

    public abstract Mono<Boolean> test(Map<String, Object> params);

}
